import CesiumUtil from "@/utils/cesiumUtil";
export default class Mark {
  constructor(option) {
    this.Vm = option.Vm;
    this.viewer = option.viewer;
    this.drawLayer = new Cesium.CustomDataSource('drawLayer');
    this.viewer.dataSources.add(this.drawLayer);

    this.handlers = null;
    this.tooltip = null;
    this.tooltipText = '';
    this.lastClickTime = null;
    this.lastClickPositionX = null;
    this.lastClickPositionY = null;
    this.util = new CesiumUtil(this.viewer);
    this.createTooltip();
  }

  loadMark(option) {
    this.m_end();

    const { type } = option;
    switch (type) {
      case '点':
        this.loadPoint(option);
        break;

      case '线':
        this.loadLine(option);
        break;

      case '面':
        this.loadSurface(option);
        break;

      default:
        break;
    }
  }

  loadPoint(option) {
    if (this.viewer && option) {
      this.m_start('单击结束');
      const { iconName, show, callback } = option;
      let position, positions = [], poiObj;
      this.handlers = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

      // 左键单击
      this.handlers.setInputAction((movement) => {
        let cartesian = this.util.getCatesian3FromPX(movement.position);
        if (cartesian && cartesian.x) {
          position = cartesian;
          positions.push(cartesian);
          this.loadLabel({ ...option, position });
        }
        if (typeof callback === 'function') {
          callback(positions, poiObj);
        }
        this.m_end();
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 移动
      this.handlers.setInputAction((movement) => {
        this.moveTooltip(movement);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // 广告牌
      const iconSize = Number(option.iconSize);
      const billboardStyle = {
        image: require(`@/assets/image/labelInfo/pointIcon/${iconName}.png`),
        width: iconSize,
        height: iconSize,
        scale: 1,
      };
      let pointEntity = new Cesium.Entity();
      pointEntity.billboard = billboardStyle;
      pointEntity.position = new Cesium.CallbackProperty(() => {
        option.position = position;
        return position;
      }, false);
      pointEntity.show = show;
      pointEntity.attribute = option;
      poiObj = this.drawLayer.entities.add(pointEntity);
    }
  }

  loadLine(option) {
    if (this.viewer && option) {
      this.m_start('单击开始，双击结束');
      const { color, lineType, show, isLabel, callback } = option;
      let positions = [], lineEntity = new Cesium.Entity(), lineObj;
      this.handlers = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

      // 左键单击
      this.handlers.setInputAction((movement) => {
        if (this.isNearPoint(movement)) return;
        let cartesian = this.util.getCatesian3FromPX(movement.position);
        if (cartesian && cartesian.x) {
          if (positions.length == 0) {
            positions.push(cartesian.clone());
          }
          positions.push(cartesian);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 鼠标移动
      this.handlers.setInputAction((movement) => {
        this.moveTooltip(movement);
        let cartesian = this.util.getCatesian3FromPX(movement.endPosition);
        if (positions.length >= 2) {
          if (cartesian && cartesian.x) {
            positions.pop();
            positions.push(cartesian);
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // 左键双击
      this.handlers.setInputAction((movement) => {
        this.m_end();
        if (positions.length >= 2) {
          positions.pop();
          isLabel && this.loadLabel({ ...option, position: positions[positions.length - 1] });
        }
        if (typeof callback === 'function') {
          callback(positions, lineObj);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

      const width = Number(option.width);
      let material = null;
      switch (lineType) {
        case 'solid':
          material = Cesium.Color.fromCssColorString(color || '#58a55c');
          break;

        case 'dashed':
          material = new Cesium.PolylineDashMaterialProperty({
            color: Cesium.Color.fromCssColorString(color || '#58a55c'),
            dashLength: 20
          });
          break;

        default:
          material = Cesium.Color.fromCssColorString(color || '#58a55c');
          break;
      }
      lineEntity.polyline = {
        width: width || 5,
        material: material,
        clampToGround: true
      };
      lineEntity.polyline.positions = new Cesium.CallbackProperty(() => {
        option.position = positions;
        return positions;
      }, false);
      lineEntity.show = show;
      lineEntity.attribute = option;
      lineObj = this.drawLayer.entities.add(lineEntity);
    }
  }

  loadSurface(option) {
    if (this.viewer && option) {
      this.m_start('单击开始，双击结束');
      const { color, alpha, show, callback } = option;
      let positions = [], polygon = new Cesium.PolygonHierarchy(), polygonEntity = new Cesium.Entity(), polyObj = null;
      const create = () => {
        let material = Cesium.Color.fromCssColorString(color);
        material.alpha = alpha;
        polygonEntity.polygon = {
          hierarchy: new Cesium.CallbackProperty(() => {
            option.position = polygon.positions;
            return polygon;
          }, false),
          material: material,
          clampToGround: true
        };
        polygonEntity.show = show;
        polygonEntity.attribute = option;
        polyObj = this.drawLayer.entities.add(polygonEntity);
      };
      this.handlers = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

      // 左键单击
      this.handlers.setInputAction((movement) => {
        if (this.isNearPoint(movement)) return;
        let cartesian = this.util.getCatesian3FromPX(movement.position);
        if (cartesian && cartesian.x) {
          if (positions.length == 0) {
            polygon.positions.push(cartesian.clone());
            positions.push(cartesian.clone());
          }
          positions.push(cartesian.clone());
          polygon.positions.push(cartesian.clone());

          if (!polyObj) create();
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 鼠标移动
      this.handlers.setInputAction((movement) => {
        this.moveTooltip(movement);
        var cartesian = this.util.getCatesian3FromPX(movement.endPosition);
        if (positions.length >= 2) {
          if (cartesian && cartesian.x) {
            positions.pop();
            positions.push(cartesian);
            polygon.positions.pop();
            polygon.positions.push(cartesian);
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // 左键双击
      this.handlers.setInputAction((movement) => {
        this.m_end();
        positions.push(positions[0]);
        this.loadLabel({ ...option, position: positions[positions.length - 1] });
        if (typeof callback === 'function') {
          callback(positions, polyObj);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    }
  }

  loadLabel(option) {
    if (this.viewer && option) {
      const { type, name, textStyle, show, position } = option;
      const { fillColor, backgroundColor } = textStyle;
      let horizontalOrigin, pixelOffset;
      if (type == '点') {
        const { textPosition } = option;
        const iconSize = Number(option.iconSize);
        const pixelOffsetX = iconSize / 2;
        switch (textPosition) {
          case 'CENTER':
            horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
            pixelOffset = new Cesium.Cartesian2(-pixelOffsetX - 25, -(pixelOffsetX + 15));
            break;

          case 'LEFT':
            horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
            pixelOffset = new Cesium.Cartesian2(-pixelOffsetX, 0);
            break;

          case 'RIGHT':
            horizontalOrigin = Cesium.HorizontalOrigin.LEFT;
            pixelOffset = new Cesium.Cartesian2(pixelOffsetX, 0);
            break;

          default:
            break;
        }
      }

      let pointEntity = new Cesium.Entity({
        position: position,
        point: {
          pixelSize: 1,
          color: new Cesium.Color(0.0, 0.0, 0.0, 0.0)
        },
        label: {
          text: name,
          font: '10px Source Han Sans CN', // 字体样式
          fillColor: Cesium.Color.fromCssColorString(fillColor), // 字体颜色
          backgroundColor: Cesium.Color.fromCssColorString(backgroundColor), // 背景颜色
          showBackground: true, // 是否显示背景颜色
          style: Cesium.LabelStyle.FILL, // label样式
          outlineWidth: 2,
          verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直位置
          horizontalOrigin: horizontalOrigin || Cesium.HorizontalOrigin.LEFT, // 水平位置
          pixelOffset: pixelOffset || new Cesium.Cartesian2(10, 0), // 偏移
          disableDepthTestDistance: Number.POSITIVE_INFINITY
        }
      });
      pointEntity.show = show;
      pointEntity.attribute = option;
      this.drawLayer.entities.add(pointEntity);
    }
  }

  locateMark(resourceId) {
    let curMark = this.drawLayer.entities._entities._array.find(el => el.attribute.resourceId == resourceId);
    if (curMark) {
      this.viewer.zoomTo(curMark);
    }
  }

  hideMark(resourceId, state) {
    let entitiesArr = this.drawLayer.entities._entities._array;
    if (!entitiesArr || !entitiesArr.length) return;
    if (resourceId) {
      for (let i = 0; i < entitiesArr.length; i++) {
        const item = entitiesArr[i];
        if (item.attribute.resourceId == resourceId) {
          item.show = state;
          item.attribute.show = state;
        }
      }
    } else {
      entitiesArr.forEach(item => {
        item.show = state;
        item.attribute.show = state;
      });
    }
  }

  renameMark(resourceId, label) {
    let entitiesArr = this.drawLayer.entities._entities._array;
    if (!resourceId || !entitiesArr || !entitiesArr.length) return;
    for (let i = 0; i < entitiesArr.length; i++) {
      const item = entitiesArr[i];
      if (item.attribute.resourceId == resourceId && item.label) {
        if (item.label.text._value != label) item.label.text._value = label;
      }
    }
  }

  removeMark(resourceId) {
    let entitiesArr = this.drawLayer ? this.drawLayer.entities._entities.values : null;
    if (!entitiesArr || !entitiesArr.length) return;
    if (resourceId) {
      for (let i = 0; i < entitiesArr.length; i++) {
        const item = entitiesArr[i];
        if (item.attribute.resourceId == resourceId) {
          this.drawLayer.entities.remove(item);
          i--;
        }
      }
    } else {
      this.drawLayer.entities.removeAll();
    }
  }

  createTooltip() {
    let tooltip = document.createElement('DIV');
    document.body.appendChild(tooltip);
    tooltip.style = 'position: absolute;background: rgba(0,0,0,0.5); z-index: 999;line-height: 18px;pointer-events: none;';
    tooltip.innerHTML = `<span style="color: #fff; font-size: 12px;padding:4px" class="tooltip-text"></span>`;
    this.tooltip = tooltip;
  }

  // 开始绘制
  m_start(text) {
    document.body.style.cursor = "crosshair";
    this.removeHandlers();
    this.showHideTooltip(true);
    setTimeout(() => {
      console.dir(this.tooltip);
      let tooltipText = this.tooltip.children[0];
      tooltipText && (tooltipText.innerText = text);
    }, 100);
  }

  // 结束绘制
  m_end() {
    document.body.style.cursor = "default";
    this.removeHandlers();
    this.showHideTooltip(false);
  }

  m_destroy() {
    this.m_end();
    this.tooltip && this.tooltip.remove();
    this.tooltip = null;
  }

  showHideTooltip(state) {
    this.tooltip && (this.tooltip.style.display = state ? 'block' : 'none');
  }

  moveTooltip(movement) {
    this.tooltip.style.left = movement.endPosition.x + 320 + 'px';
    this.tooltip.style.top = movement.endPosition.y + 100 + 'px';
  }

  removeHandlers() {
    this.handlers && this.handlers.destroy();
    this.handlers = null;
  }

  isNearPoint(movement) {
    let times = new Date().getTime() - (this.lastClickTime || 0);
    // 屏蔽单击时间很近的点
    if (this.lastClickTime && times < 200) return true;
    this.lastClickTime = new Date().getTime();
    // 屏蔽单击像素很近的点
    if (this.lastClickPositionX && Math.abs(this.lastClickPositionX - movement.x) < 10 && Math.abs(this.lastClickPositionY - movement.y) < 10) return true;
    this.lastClickPositionX = movement.x;
    this.lastClickPositionY = movement.y;
    return false;
  }

  loadMarkFile(data) {
    for (let i = 0; i < data.length; i++) {
      const item = data[i];
      const attribute = item.attribute || null;
      if (!attribute) break;
      const type = attribute.type || '';
      const show = attribute.show;
      let labelPosition = null;
      switch (type) {
        case '点':
          const iconName = attribute.iconName || '';
          const iconSize = Number(attribute.iconSize) || '';
          const position = attribute.positions ? attribute.positions[0] : { x: 1.0, y: 1.0, z: 1.0 };
          labelPosition = new Cesium.Cartesian3(position.x, position.y, position.z);

          const billboardStyle = {
            image: require(`@/assets/image/labelInfo/pointIcon/${iconName}.png`),
            width: iconSize,
            height: iconSize,
            scale: 1,
          };
          let pointEntity = new Cesium.Entity();
          pointEntity.billboard = billboardStyle;
          pointEntity.position = labelPosition;
          pointEntity.show = show;
          pointEntity.attribute = attribute;
          this.drawLayer.entities.add(pointEntity);
          break;

        case '线':
          const color = attribute.color || '#58a55c';
          const lineType = attribute.lineType || 'solid';
          const width = Number(attribute.width) || 3;
          const positions = attribute.positions || [{ x: 1.0, y: 1.0, z: 1.0 }, { x: 2.0, y: 2.0, z: 2.0 }];
          let linePositions = positions.map(e => { return new Cesium.Cartesian3(e.x, e.y, e.z); });
          labelPosition = linePositions[linePositions.length - 1];
          let material = null;
          switch (lineType) {
            case 'solid':
              material = Cesium.Color.fromCssColorString(color);
              break;

            case 'dashed':
              material = new Cesium.PolylineDashMaterialProperty({
                color: Cesium.Color.fromCssColorString(color),
                dashLength: 20
              });
              break;

            default:
              material = Cesium.Color.fromCssColorString(color);
              break;
          }
          let lineEntity = new Cesium.Entity();
          lineEntity.polyline = {
            width: width,
            material: material,
            clampToGround: true
          };
          lineEntity.polyline.positions = linePositions;
          lineEntity.show = show;
          lineEntity.attribute = attribute;
          this.drawLayer.entities.add(lineEntity);
          break;

        case '面':
          const surfaceColor = attribute.color || '#58a55c';
          const alpha = attribute.alpha || 0.5;
          const positions1 = attribute.positions || [{ x: 1.0, y: 1.0, z: 1.0 }, { x: 2.0, y: 2.0, z: 2.0 }];
          let surfacePositions = positions1.map(e => { return new Cesium.Cartesian3(e.x, e.y, e.z); });
          labelPosition = surfacePositions[surfacePositions.length - 1];
          let surfaceMaterial = Cesium.Color.fromCssColorString(surfaceColor);
          surfaceMaterial.alpha = alpha;
          let polygonEntity = new Cesium.Entity();
          let polygon = new Cesium.PolygonHierarchy();
          polygon.positions = surfacePositions;
          polygonEntity.polygon = {
            hierarchy: polygon,
            material: surfaceMaterial,
            clampToGround: true
          };
          polygonEntity.show = show;
          polygonEntity.attribute = attribute;
          this.drawLayer.entities.add(polygonEntity);
          break;

        default:
          break;
      }
      const resourceId = attribute.resourceId || '';
      const name = attribute.name || '';
      const textStyle = attribute.textStyle || {
        "backgroundColor": "#373737",
        "fillColor": "#fff",
        "isCheck": true
      };
      const position = labelPosition;
      this.loadLabel({ resourceId, type, name, textStyle, position, show });
    }
  }

  destroy() {
    this.m_destroy();
    this.removeMark();
    this.drawLayer && this.viewer.dataSources.remove(this.drawLayer);
    this.drawLayer = null;
  }
}